package org.javahispano.javacup.tacticas_aceptadas.sjvc;

import java.awt.Color;
import org.javahispano.javacup.modelo.*;


import org.javahispano.javacup.tacticas_aceptadas.sjvc.SubTacticasAtaque.*;
import org.javahispano.javacup.tacticas_aceptadas.sjvc.SubTacticasDefensa.*;

import java.util.LinkedList;
import java.util.List;


public class TacticaBalsares implements Tactica {

    Posicion alineacion1[]=new Posicion[]{
        new Posicion(0.2595419847328244,-50.41044776119403),
        new Posicion(-9.034965034965035,-30.88235294117647),
        new Posicion(11.412587412587413,-31.59502262443439),
        new Posicion(25.678321678321677,-24.230769230769234),
        new Posicion(-25.678321678321677,-24.468325791855204),
        new Posicion(1.188811188811189,-11.165158371040723),
        new Posicion(-18.307692307692307,-1.900452488687783),
        new Posicion(20.685314685314687,-3.5633484162895925),
        new Posicion(-0.23776223776223776,25.418552036199095),
        new Posicion(19.734265734265733,30.6447963800905),
        new Posicion(-17.594405594405593,33.257918552036195)
    };

    Posicion alineacion2[]=new Posicion[]{
        new Posicion(0.2595419847328244,-50.41044776119403),
        new Posicion(0.23776223776223776,-29.457013574660635),
        new Posicion(18.307692307692307,-27.794117647058822),
        new Posicion(27.104895104895103,-5.701357466063349),
        new Posicion(-15.454545454545453,-23.993212669683256),
        new Posicion(0.4755244755244755,-12.352941176470589),
        new Posicion(-25.44055944055944,-3.800904977375566),
        new Posicion(13.314685314685315,20.429864253393667),
        new Posicion(-10.6993006993007,20.192307692307693),
        new Posicion(27.34265734265734,33.49547511312217),
        new Posicion(-27.58041958041958,35.63348416289593)
    };

    Posicion alineacion3[]=new Posicion[]{
        new Posicion(0.2595419847328244,-50.41044776119403),
        new Posicion(-11.174825174825173,-32.54524886877828),
        new Posicion(10.6993006993007,-32.07013574660634),
        new Posicion(29.006993006993007,-27.08144796380091),
        new Posicion(-29.006993006993007,-24.468325791855204),
        new Posicion(-5.944055944055944,-13.778280542986426),
        new Posicion(-18.545454545454543,-17.816742081447966),
        new Posicion(5.468531468531468,-13.778280542986426),
        new Posicion(18.78321678321678,-19.2420814479638),
        new Posicion(17.11888111888112,28.98190045248869),
        new Posicion(-17.594405594405593,29.21945701357466)
    };

    class TacticaDetalleImpl implements TacticaDetalle {

        public String getNombre() {
            return "Los Balsares";
        }

        public String getPais() {
            return "España";
        }

        public String getEntrenador() {
            return "Sergio Viudes";
        }

        public Color getColorCamiseta() {
            return new Color(255, 255, 255);
        }

        public Color getColorPantalon() {
            return new Color(255, 255, 255);
        }

        public Color getColorFranja() {
            return new Color(0, 153, 51);
        }

        public Color getColorCalcetas() {
            return new Color(255, 255, 255);
        }

        public Color getColorPortero() {
            return new Color(0, 0, 0        );
        }

        public EstiloUniforme getEstilo() {
            return EstiloUniforme.FRANJA_HORIZONTAL;
        }

        public Color getColorCamiseta2() {
            return new Color(255, 0, 0);
        }

        public Color getColorPantalon2() {
            return new Color(0, 0, 255);
        }

        public Color getColorFranja2() {
            return new Color(0, 0, 255);
        }

        public Color getColorCalcetas2() {
            return new Color(0, 0, 255);
        }

        public Color getColorPortero2() {
            return new Color(0, 0, 0        );
        }

        public EstiloUniforme getEstilo2() {
            return EstiloUniforme.LINEAS_VERTICALES;
        }

        class JugadorImpl implements JugadorDetalle {

            String nombre;
            int numero;
            Color piel, pelo;
            double velocidad, remate, presicion;
            boolean portero;
            Posicion posicion;

            public JugadorImpl(String nombre, int numero, Color piel, Color pelo,
                    double velocidad, double remate, double presicion, boolean portero) {
                this.nombre=nombre;
                this.numero=numero;
                this.piel=piel;
                this.pelo=pelo;
                this.velocidad=velocidad;
                this.remate=remate;
                this.presicion=presicion;
                this.portero=portero;
            }

            public String getNombre() {
                return nombre;
            }

            public Color getColorPiel() {
                return piel;
            }

            public Color getColorPelo() {
                return pelo;
            }

            public int getNumero() {
                return numero;
            }

            public boolean esPortero() {
                return portero;
            }

            public double getVelocidad() {
                return velocidad;
            }

            public double getRemate() {
                return remate;
            }

            public double getPresicion() {
                return presicion;
            }

        }

        public JugadorDetalle[] getJugadores() {
            return new JugadorDetalle[]{
                new JugadorImpl("Aitor Tilla", 1, new Color(255,200,150), new Color(255,204,153),1.0d,0.49d,0.69d, true),
                new JugadorImpl("Mariano Tevayas", 2, new Color(255,200,150), new Color(50,0,0),0.99d,0.69d,0.8d, false),
                new JugadorImpl("Alberto Carlos Huevos", 3, new Color(255,200,150), new Color(50,0,0),0.91d,0.75d,0.74d, false),
                new JugadorImpl("Armando Adistancia", 4, new Color(255,200,150), new Color(153,153,0),0.92d,0.69d,0.76d, false),
                new JugadorImpl("Chema Pamundi", 5, new Color(255,200,150), new Color(50,0,0),0.84d,0.56d,0.9d, false),
                new JugadorImpl("Josechu Leton", 6, new Color(255,200,150), new Color(50,0,0),1.0d,0.66d,0.91d, false),
                new JugadorImpl("Alan Brito", 7, new Color(153,102,0), new Color(0,0,0),1.0d,0.76d,0.87d, false),
                new JugadorImpl("Alberto Cadiscos", 8, new Color(255,200,150), new Color(50,0,0),0.63d,0.89d,1.0d, false),
                new JugadorImpl("Juanjo Derqueca Bron", 9, new Color(255,200,150), new Color(50,0,0),0.67d,1.0d,1.0d, false),
                new JugadorImpl("Erique Cido", 10, new Color(204,102,0), new Color(0,0,0),0.7d,1.0d,1.0d, false),
                new JugadorImpl("Andres Trozado", 11, new Color(255,200,150), new Color(50,0,0),0.68d,1.0d,1.0d, false)
            };
        }
    }

    TacticaDetalle detalle=new TacticaDetalleImpl();
    public TacticaDetalle getDetalle() {
        return detalle;
    }

    public Posicion[] getPosicionSaca(SituacionPartido sp) {
    return alineacion2;
    }

    public Posicion[] getPosicionRecive(SituacionPartido sp) {
    return alineacion3;
    }

    /*Inicio de codigo de Sergio*/
    private boolean debugMode = false;
    private double kDistanciaSalePorteroX = 0;
    private double kDistanciaSalePorteroY = 1;
    private double kDistanciaPorteroAlerta = Constantes.LARGO_CAMPO_JUEGO / (double)8;
    
    private SituacionPartidoSergio spAnterior;
    private List<SubTactica> subTacticasAtaque;
    private List<SubTactica> subTacticasDefensa;
    private int indiceSTAEnUso;
    private int indiceSTDEnUso;
    private boolean buscarMejorTacticaDefensa;
    
    public TacticaBalsares(){
    	subTacticasAtaque = new LinkedList<SubTactica>();
    	subTacticasDefensa = new LinkedList<SubTactica>();
    	spAnterior = new SituacionPartidoSergio();
    	buscarMejorTacticaDefensa = false;
    	
    	//A�adir subtacticas a usar
    	//Ataque
    	subTacticasAtaque.add(new STACentraPorLaBanda());
    	subTacticasAtaque.add(new STAPaseAlMamonReforzado());
    	subTacticasAtaque.add(new STAPaseAlMamon());
    	//Defensa
    	subTacticasDefensa.add(new STDDespejarCubriendoDelanteros());
    	subTacticasDefensa.add(new STDDespejar());
    	subTacticasDefensa.add(new STDLosTresPorteros());    	
    	
    	//Comenzar con las tacticas en orden
    	indiceSTAEnUso = 0;
    	indiceSTDEnUso = 0;
    }

    public List<Comando> ejecutar(SituacionPartido sp) {
    	//Crea una lista de comandos
    	List<Comando> comandos = new LinkedList<Comando>();
    	
    	//Ir a la alineacion
        for (int i = 1; i < 11; i++)
            comandos.add(new ComandoIrA(i, alineacion1[i]));
        
        //Una tactica de ataque, una vez elegida, no se puede cambiar hasta que pase 1/8 del partido (sino que cachondeo es este??)
        //Si voy ganando no me preocupo de cambiar la tactica de ataque
        if(sp.iteracion() == 0 || (subTacticasAtaque.get(indiceSTAEnUso).iteracionesConsecutivas > Constantes.ITERACIONES / 8) && sp.golesPropios() <= sp.golesRival() ){
        	//Elegimos la mejor subtactica de ataque (Si hemos usado 1/4 de partido la misma táctica y no hemos marcado goles con ella, la cambiamos)
        	int indiceMejorSTA = SubTactica.ObtenerLaMejor(subTacticasAtaque, sp, indiceSTAEnUso, subTacticasAtaque.get(indiceSTAEnUso).golesPropios() == 0 && subTacticasAtaque.get(indiceSTAEnUso).iteracionesConsecutivas() > Constantes.ITERACIONES/4);
	        if(indiceSTAEnUso != indiceMejorSTA || sp.iteracion() == 0){
	        	indiceSTAEnUso = indiceMejorSTA;
	        	Log(sp, "Tactica ataque cambiada a: " + subTacticasAtaque.get(indiceSTAEnUso).getClass().toString() + ". F.U: " + subTacticasAtaque.get(indiceSTAEnUso).factorUsabilidad(sp) +  "\n");
	        }
        }
        //Elegimos la mejor subtactica de defensa la primera vez o cuando la lo indique "buscarMejorTacticaDefensa"
        if(sp.iteracion() == 0 || buscarMejorTacticaDefensa){
	        int indiceMejorSTD = SubTactica.ObtenerLaMejor(subTacticasDefensa, sp, indiceSTDEnUso);
	        if(indiceSTDEnUso != indiceMejorSTD || sp.iteracion() == 0){
	        	indiceSTDEnUso = indiceMejorSTD;
	        	Log(sp, "Tactica defensa cambiada a: " + subTacticasDefensa.get(indiceSTDEnUso).getClass().toString() + ". F.U: " + subTacticasDefensa.get(indiceSTDEnUso).factorUsabilidad(sp) +  "\n");
	        }
        }
        //Elegimos la mejor subtactica de defensa cada vez que encajamos un gol
        buscarMejorTacticaDefensa = sp.golesRival() > spAnterior.golesRival();
        
    	//Ejecutar las tacticas en uso 
        //Si he pasado de medio campo ejecutamos primero la defensa, sino el ataque)
        boolean ataque = Constantes.centroArcoInf.distancia(sp.balon()) < Constantes.LARGO_CAMPO_JUEGO/2;
		
        for(Comando cmd : (!ataque ? subTacticasDefensa : subTacticasAtaque).get(!ataque ? indiceSTDEnUso : indiceSTAEnUso).ejecutar(sp, spAnterior))
			comandos.add(cmd);
        for(Comando cmd : (ataque ? subTacticasDefensa : subTacticasAtaque).get(ataque ? indiceSTDEnUso : indiceSTAEnUso).ejecutar(sp, spAnterior))
			comandos.add(cmd);
    		
    	//MOVIMIENTO DEL PORTERO
        
        //Si saco, voy a por el bal�n para chutarlo
        if(sp.saco() && sp.balon().distancia(sp.misJugadores()[0]) <= Constantes.LARGO_AREA_CHICA)
        	comandos.add(new ComandoIrA(0, sp.balon())); 
    	//Si no, si el balon esta cerca, va a buscarlo, sino va a su posicion (para que no se vea descaradamente que el portero siempre esta buscando la pelota)
        else if(sp.balon().distancia(sp.misJugadores()[0]) <= kDistanciaPorteroAlerta)
        {
        	double x,y;
        	//Si la pelota esta dentro de la zona del portero, va a por ella
        	if(Math.abs(sp.balon().getX()) - kDistanciaSalePorteroX < Constantes.LARGO_ARCO/2)
        	{
        		//Si la pelota esta lejos del portero, tendra en cuenta que no tiene que seguir "cegado" al eje X de la pelota, sino que ha de mantener una distancia por si se la tiran de forma diagonal
        		double factorAcercamientoEjeX = ((kDistanciaPorteroAlerta - (sp.balon().distancia(Constantes.centroArcoInf) > kDistanciaPorteroAlerta ? kDistanciaPorteroAlerta : sp.balon().distancia(Constantes.centroArcoInf))) / kDistanciaPorteroAlerta);
        		x = sp.balon().getX() * factorAcercamientoEjeX; 
        	}
        	else //Si no va a l limite de donde puede ir el portero
        		x = (Constantes.LARGO_ARCO/2 + kDistanciaSalePorteroX) * (sp.balon().getX() < 0 ? -1 : 1);
        	
        	//Con la y hace lo mismo que con la x (va a por la pelota o va al maximo)
        	y = sp.balon().getY() < sp.misJugadores()[0].getY() ? sp.balon().getY() : -Constantes.LARGO_CAMPO_JUEGO/2 + kDistanciaSalePorteroY;
        	
        	comandos.add(new ComandoIrA(0, new Posicion(x,y))); 
        }//sino vuelvo a la alineaci�n
    	else
    		comandos.add(new ComandoIrA(0, alineacion1[0]));
        
    	//Si puede chutar, chutara para despejar
    	if(sp.balon().distancia(sp.misJugadores()[0]) <= Constantes.DISTANCIA_CONTROL_BALON_PORTERO)
    		Comandos.DespejarDesdeLaPorteria(sp, 0, comandos);
    	
    	//Si hay que salir a por la pelota, se sale
    	if(sp.balon().distancia(sp.misJugadores()[0]) <= Constantes.DISTANCIA_PENAL * 2 &&  sp.balon().distancia(sp.misJugadores()[0]) < sp.balon().distancia( sp.rivales()[sp.balon().indiceMasCercano(sp.rivales())]) )
    		comandos.add(new ComandoIrA(0, sp.balon()));
    		
    	//Guardar la situacion del partido
        spAnterior.setGolesPropios(sp.golesPropios());
        spAnterior.setGolesRival(sp.golesRival());
        spAnterior.setIteracion(sp.iteracion());
    		
    	//Devolver comandos a ejecutar
    	return comandos;
    }
    
	public void Log(SituacionPartido sp, String message){
		if(debugMode)
			System.out.print(sp.iteracion() + ": " + message);
	}
    
    /*Fin de codigo de Sergio*/
    
}